from machine import I2C,Pin,SPI
import time,framebuf,math,gc,struct
from micropython import const

i2c = I2C(2, freq=100_000) 
print('i2c addr scan:',[hex(x) for x in i2c.scan()])

# 装饰器用于统计函数执行时间
def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.ticks_ms()  # 记录函数开始执行的时间
        result = func(*args, **kwargs)  # 调用原函数并获取结果
        end_time = time.ticks_ms()  # 记录函数执行结束的时间
        execution_time = end_time - start_time  # 计算函数执行时间
        print("func {} time: {} ms".format(func.__name__, execution_time))
        return result  # 返回原函数的结果
    return wrapper

# 常量定义
CST816D_REG_GESTURE_ID = 0x01  # 手势寄存器
CST816D_REG_FINGER_NUM = 0x02  # 手指数量
CST816D_REG_XPOS_HIGH = 0x03  # X坐标高四位
CST816D_REG_XPOS_LOW = 0x04  # X坐标低八位
CST816D_REG_YPOS_HIGH = 0x05  # Y坐标高四位
CST816D_REG_YPOS_LOW = 0x06  # Y坐标低八位
CST816D_REG_WORK_MODE = 0xA5  # 工作模式
CST816D_REG_CHIP_ID = 0xA7  # 芯片型号
CST816D_REG_VENDOR_ID = 0xA8  # 厂商型号
CST816D_REG_FW_VERSION = 0xA9  # 固件版本
CST816D_REG_MOTION_MASK = 0xEC  # 触发动作
CST816D_REG_AUTOSLEEP_TIME = 0xF9  # 自动休眠
CST816D_REG_IRQ_CTRL = 0xFA  # 中断控制
CST816D_REG_AUTO_RESET = 0xFB  # 无手势休眠
CST816D_REG_LONGPRESS_TIME = 0xFC  # 长按休眠
CST816D_REG_DISABLE_AUTOSLEEP = 0xFE  # 使能低功耗模式

CST816D_GESTURE_NONE = 0x00
CST816D_GESTURE_SLIDEDOWN = 0x01
CST816D_GESTURE_SLIDEUP = 0x02
CST816D_GESTURE_SLIDELEFT = 0x03
CST816D_GESTURE_SLIDERIGHT = 0x04
CST816D_GESTURE_SINGLETAP = 0x05
CST816D_GESTURE_DOUBLETAP = 0x0B
CST816D_GESTURE_LONGPRESS = 0x0C

CST816D_I2C_7BIT_ADDR = 0x15

LOW = 0
HIGH = 1

class CST816D(object):
    def __init__(self,i2c,tprst,tpint,addr=CST816D_I2C_7BIT_ADDR):
        self._i2c = i2c
        self.tprst = tprst
        self.tpint = tpint
        self.address = addr  # set touch panel 7bit i2c slave address
        self.width = 240
        self.height = 280
        self.chip,self.vendor,self.version=0,0,0
        self.init()
        self.get_info()
        print('chip=0x{:02X},vendor=0x{:02X},version=0x{:02X}'.format(self.chip,self.vendor,self.version))
        
    def reset(self):
        self.tprst.value(0)# the spec requires at least 5ms
        time.sleep_ms(10)        
        self.tprst.value(1)# the spec requires a maximum wait of 100
        time.sleep_ms(120)     
    
    def init(self):
        self.reset() # reset sequence
        # configuration the moion mask
        #   [2] EnConLR - Continuous operation can slide around
        #   [1] EnConUD - Slide up and down to enable continuous operation
        #   [0] EnDClick - Enable Double-click action        
        self._i2c.writeto_mem(self.address,CST816D_REG_MOTION_MASK, b'\x03')
        # configuration the irq control
        #   [7] EnTest - Interrupt pin to test, enable automatic periodic issued after a low pulse.
        #   [6] EnTouch - When a touch is detected, a periodic pulsed Low.
        #   [5] EnChange - Upon detecting a touch state changes, pulsed Low.
        #   [4] EnMotion - When the detected gesture is pulsed Low.
        #   [0] OnceWLP - Press gesture only issue a pulse signal is low.        
        self._i2c.writeto_mem(self.address,CST816D_REG_IRQ_CTRL, b'\x70')

    def deinit(self):
        pass
    
    # 进入睡眠模式
    def sleepin(self):
        self.reset() # reset sequence
        self._i2c.writeto_mem(self.address,CST816D_REG_WORK_MODE, b'\x03')
        
    def wakeup(self):   
        self.init()
    
    def get_info(self):
        # read 0xA7 ~ 0xA9 reg's values , convert to infomation
        self.chip,self.vendor,self.version = self._i2c.readfrom_mem(self.address,CST816D_REG_CHIP_ID, 3)    
 
    def get_gesture_str(self,v):
        if v == CST816D_GESTURE_NONE:
            return "NONE"
        elif v == CST816D_GESTURE_SLIDEUP:
            return "UP"
        elif v == CST816D_GESTURE_SLIDEDOWN:
            return "DOWN"
        elif v == CST816D_GESTURE_SLIDELEFT:
            return "LEFT"
        elif v == CST816D_GESTURE_SLIDERIGHT:
            return "RIGHT"
        elif v == CST816D_GESTURE_SINGLETAP:
            return "SINGLE"
        elif v == CST816D_GESTURE_DOUBLETAP:
            return "DOUBLE"
        elif v == CST816D_GESTURE_LONGPRESS:
            return "LONGPRESS"
        else:
            return "UNKNOW"
     
    # 获取手势
    def get_gesture(self):
        # read 0x00 ~ 0x06 reg's values
        val = self._i2c.readfrom_mem(self.address,0x00, 7) 
        if all(x == 0 for x in val) is True:#al 函数检查可迭代对象中的所有元素是否都为 True
            pressed = False
            gesture = CST816D_GESTURE_NONE
            x,y = 0,0
            return -1,pressed,gesture,x,y
        
        # calculate the xy coordinates
        x = ((val[CST816D_REG_XPOS_HIGH] & 0x0f) << 8) | val[CST816D_REG_XPOS_LOW]
        y = ((val[CST816D_REG_YPOS_HIGH] & 0x0f) << 8) | val[CST816D_REG_YPOS_LOW]
        if x >= self.width or y >= self.height:
            pressed = False
            gesture = CST816D_GESTURE_NONE
            x,y = 0,0
            return -2,pressed,gesture,x,y
        
        # record pressed status by touch points number
        pressed = True if val[CST816D_REG_FINGER_NUM] else False
        gesture = val[CST816D_REG_GESTURE_ID]
        return 0,pressed,self.get_gesture_str(gesture),x,y
 
    # 获取坐标
    def get_coord(self):
        return self.get_gesture()    
           
    @property           
    def get_action(self):
        return True if self.tpint.value()==0 else False #检测到手势时，发出低脉冲
    
#----------------------------------------------------------------------------------------------
def Color(r, g, b): #rgb888_to_rgb565
    def swap(c):
        return  ((c & 0xff) << 8) | ((c >> 8) & 0xff)
    res = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
    return swap(res)

# 基本颜色
RED = Color(255, 0, 0)
GREEN = Color(0, 255, 0)
BLUE = Color(0, 0, 255)
YELLOW = Color(255, 255, 0)
CYAN = Color(0, 255, 255)
MAGENTA = Color(255, 0, 255)
WHITE = Color(255, 255, 255)
BLACK = Color(0, 0, 0)
# 灰色系
LIGHT_GRAY = Color(211, 211, 211)
GRAY = Color(128, 128, 128)
DARK_GRAY = Color(169, 169, 169)
SILVER = Color(192, 192, 192)
# 棕色系
BROWN = Color(165, 42, 42)
CHOCOLATE = Color(210, 105, 30)
SADDLE_BROWN = Color(139, 69, 19)
TAN = Color(210, 180, 140)
# 粉色系
PINK = Color(255, 192, 203)
LIGHT_PINK = Color(255, 182, 193)
HOT_PINK = Color(255, 105, 180)
DEEP_PINK = Color(255, 20, 147)
# 橙色系
ORANGE = Color(255, 165, 0)
DARK_ORANGE = Color(255, 140, 0)
ORANGE_RED = Color(255, 69, 0)
# 紫色系
PURPLE = Color(128, 0, 128)
VIOLET = Color(238, 130, 238)
INDIGO = Color(75, 0, 130)
DARK_VIOLET = Color(148, 0, 211)

class ST7789(framebuf.FrameBuffer):
    def __init__(self, spi, rst, dc, cs, bl=None, width=None, height=None,rotate_degree=0, rgb=True):
        rotateDir = [0x00,0x60,0xC0,0xA0] #ROTATE_0:0x00   ROTATE_90:0x60  ROTATE_180:0xC0  ROTATE_270:0xA0
        self.rgb = rgb
        self.width,self.height = width,height
        self.xshift,self.yshift = 0,0         
        if rotate_degree==0:    
            self.rotate = rotateDir[0]
            self.width,self.height = width,height
            self.xshift,self.yshift = 0,20
        elif rotate_degree==90: 
            self.rotate = rotateDir[1]        
            self.width,self.height = height,width
            self.xshift,self.yshift = 20,0             
        elif rotate_degree==180:     
            self.rotate = rotateDir[2]        
            self.width,self.height = width,height
            self.xshift,self.yshift = 0,20         
        else: #270
            self.rotate = rotateDir[3]        
            self.width,self.height = height,width
            self.xshift,self.yshift = 20,0                
        
        self.spi = spi
        self.rst = rst
        self.dc = dc
        self.cs = cs
        if bl is not None:
            self.bl = bl
 
        self.fg_color = BLACK  # 默认前景色
        self.bg_color = WHITE  # 默认背景色       
        
        gc.collect()
        self.buffer = bytearray(self.height * self.width * 2)
        super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
        self.init()
        self.set_windows(0,0,self.width,self.height)
        self.clear(WHITE)
 
    def set_fg_color(self, color):
        self.fg_color = color

    def set_bg_color(self, color):
        self.bg_color = color

    def set_windows(self, x,y,w,h):
        xs = struct.pack('>2H',x+self.xshift,x+w+self.xshift-1)
        ys = struct.pack('>2H',y+self.yshift,y+h+self.yshift-1) #yshift=20

        self.write_cmd(0x2A)
        self.write_data(xs)
 
        self.write_cmd(0x2B)
        self.write_data(ys)
 
        self.write_cmd(0x2C)
 
    def init(self):
        self.reset()

        self.write_cmd(0x36) #rotate
        self.write_data(bytearray([self.rotate]))
        
        self.write_cmd(0x21)
        
        self.write_cmd(0x3A)
        self.write_data(bytearray([0x05]))
        
        self.write_cmd(0xB2)
        self.write_data(bytearray([0x0C, 0x0C, 0x00,0x33,0x33]))
        
        self.write_cmd(0xB7)
        self.write_data(bytearray([0x35]))
    
        self.write_cmd(0xBB)
        self.write_data(bytearray([0x1F]))
        
        self.write_cmd(0xC0)
        self.write_data(bytearray([0x2C]))

        self.write_cmd(0xC2)
        self.write_data(bytearray([0x01]))

        self.write_cmd(0xC3)
        self.write_data(bytearray([0x1D]))
        
        self.write_cmd(0xC4)
        self.write_data(bytearray([0x20]))
        
        self.write_cmd(0xC6)
        self.write_data(bytearray([0x0F]))
        
        self.write_cmd(0xD0)
        self.write_data(bytearray([0xA4,0xA1]))

        self.write_cmd(0xE4)
        self.write_data(bytearray([0x27, 0x00, 0x00]))

        self.write_cmd(0xE0)
        self.write_data(bytearray([0xd0, 0x00, 0x14, 0x15, 0x13, 0x2c, 0x42, 0x43, 0x4e, 0x09, 0x16, 0x14, 0x18, 0x21]))
        self.write_cmd(0xE1)        
        self.write_data(bytearray([0xd0, 0x00, 0x14, 0x15, 0x13, 0x0b, 0x43, 0x55, 0x53, 0x0c, 0x17, 0x14, 0x23, 0x20]))
        
        self.write_cmd(0x11)
        self.write_cmd(0x29)

    def reset(self):        
        self.rst.value(0)
        time.sleep_ms(100)
        self.rst.value(1)
        time.sleep_ms(120)
 
    def write_cmd(self, cmd):
        self.dc.value(0)
        self.cs.value(0)
        self.spi.write(bytearray([cmd]))
        self.cs.value(1)
 
    def write_data(self, buf):
        self.dc.value(1)
        self.cs.value(0)
        if isinstance(buf, int):
            buf = bytearray([buf])
        self.spi.write(buf)
        self.cs.value(1)

    def back_light(self, value):
        self.bl.value(1)
    
    @measure_time
    def clear(self,c):
        self.fill(c)
        self.show()
        
    #@measure_time
    def show(self):        
        self.set_windows(0,0,self.width,self.height)
        self.write_data(self.buffer)
 
    # 中点圆算法绘制圆弧
    # 参数：圆心坐标 (x0, y0)，半径 r，起始角度 start_angle，结束角度 end_angle，颜色 color
    def drawArc(self,x0, y0, r, start_angle, end_angle):
        x = r
        y = 0
        err = 1 - r
        # 辅助函数：计算点相对于圆心的角度
        def get_angle(dx, dy):
            angle = math.atan2(dy, dx) * 180 / math.pi
            if angle < 0:
                angle += 360
            return angle
        while x >= y:
            # 计算 8 个对称点相对于圆心的角度和坐标
            dx = [x, -x, x, -x, y, -y, y, -y]
            dy = [y, y, -y, -y, x, x, -x, -x]
            for i in range(8):
                angle = get_angle(dx[i], dy[i])
                if start_angle <= angle <= end_angle:
                    self.pixel(x0 + dx[i], y0 + dy[i], self.fg_color)
            if err < 0:
                err += 2 * y + 3
            else:
                err += 2 * (y - x) + 5
                x -= 1
            y += 1
            
    # 绘制圆角矩形函数
    # 参数：左上角坐标 (x1, y1)，宽度 width，高度 height，圆角半径 r，是否填充 fill，颜色 color
    def drawRoundRect(self,x1, y1, width, height, r, fill):
        x2 = x1 + width - 1
        y2 = y1 + height - 1
        # 确保圆角半径不超过矩形短边的一半
        r = min(r, width // 2, height // 2)       
        # 绘制四条边 & 四个角的圆弧
        if not fill:
            self.line(x1 + r, y1, x2 - r, y1, self.fg_color)  # 上边
            self.line(x1 + r, y2, x2 - r, y2, self.fg_color)  # 下边
            self.line(x1, y1 + r, x1, y2 - r, self.fg_color)  # 左边
            self.line(x2, y1 + r, x2, y2 - r, self.fg_color)  # 右边
            self.drawArc(x1 + r, y1 + r, r, 180, 270)  # 左上角
            self.drawArc(x2 - r, y1 + r, r, 270, 360)  # 右上角
            self.drawArc(x1 + r, y2 - r, r, 90, 180)   # 左下角
            self.drawArc(x2 - r, y2 - r, r, 0, 90)     # 右下角
        # 填充内部区域
        else:        
            pass

    # Bresenham 画圆算法
    def drawCircle(self,x0, y0, r, fill):
        x = 0
        y = r
        d = 3 - 2 * r
        def draw_symmetric_points(x, y):
            # 绘制圆上的 8 个对称点
            if not fill:
                self.pixel(x0 + x, y0 + y, self.fg_color)
                self.pixel(x0 - x, y0 + y, self.fg_color)
                self.pixel(x0 + x, y0 - y, self.fg_color)
                self.pixel(x0 - x, y0 - y, self.fg_color)
                self.pixel(x0 + y, y0 + x, self.fg_color)
                self.pixel(x0 - y, y0 + x, self.fg_color)
                self.pixel(x0 + y, y0 - x, self.fg_color)
                self.pixel(x0 - y, y0 - x, self.fg_color)
            else:
                # 填充圆，通过绘制水平线段来实现
                self.line(x0 - x, y0 + y, x0 + x, y0 + y, self.fg_color)
                self.line(x0 - x, y0 - y, x0 + x, y0 - y, self.fg_color)
                self.line(x0 - y, y0 + x, x0 + y, y0 + x, self.fg_color)
                self.line(x0 - y, y0 - x, x0 + y, y0 - x, self.fg_color)
        while x <= y:
            draw_symmetric_points(x, y)
            if d < 0:
                d = d + 4 * x + 6
            else:
                d = d + 4 * (x - y) + 10
                y = y - 1
            x = x + 1
            
    # 绘制三角形函数
    def drawTriangle(self,x1, y1, x2, y2, x3, y3, fill):
        if not fill:
            # 不填充，只绘制三条边
            self.line(x1, y1, x2, y2, self.fg_color)
            self.line(x2, y2, x3, y3, self.fg_color)
            self.line(x3, y3, x1, y1, self.fg_color)
            return
        # 对三个点按 y 坐标排序
        points = [(x1, y1), (x2, y2), (x3, y3)]
        points.sort(key=lambda p: p[1])
        y_min = points[0][1]
        y_mid = points[1][1]
        y_max = points[2][1]
        x0, y0 = points[0]
        x1, y1 = points[1]
        x2, y2 = points[2]
        # 避免除零错误
        def calculate_slope(x0, y0, x1, y1):
            dy = y1 - y0
            return (x1 - x0) / dy if dy != 0 else 0
        # 计算斜率
        slope_left = calculate_slope(x0, y0, x2, y2)
        slope_right_1 = calculate_slope(x0, y0, x1, y1)
        slope_right_2 = calculate_slope(x1, y1, x2, y2)
        # 绘制上半部分三角形
        left_x = x0
        right_x = x0
        for y in range(y_min, y_mid):
            self.line(int(left_x), y, int(right_x), y, self.fg_color)
            left_x += slope_left
            right_x += slope_right_1
        # 绘制中间那条线
        self.line(int(left_x), y_mid, int(x1), y_mid, self.fg_color)
        # 绘制下半部分三角形
        right_x = x1
        for y in range(y_mid + 1, y_max + 1):
            self.line(int(left_x), y, int(right_x), y, self.fg_color)
            left_x += slope_left
            right_x += slope_right_2   
            
    def _fill_rect(self, x, y, w, h):
        pass
        '''
        if x < 0 or x + w > self.width or y < 0 or y + h > self.height:
            return
        self.set_window(x, y, x + w - 1, y + h - 1)
        pixels = w * h
        color_bytes = color.to_bytes(2, 'big')
        data = color_bytes * pixels
        self.write_data(data)
        '''

    def display_seg7(self,x,y,num):
        w,h = 16,29
        seg7List=[
            [0x7FFC,0xBFFA,0xDFF6,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xC006,0x8002,0x0000,0x8002,0xC006,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xDFF6,0xBFFA,0x7FFC],
            [0x20,0x60,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x60,0x20,0x00,0x20,0x60,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x60,0x60,0x20],
            [0xFFFC,0x7FFA,0x3FF6,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x0006,0x3FFA,0x7FFC,0xBFF8,0xC000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xDFF8,0xBFFC,0x7FFE],
            [0xFFFC,0x7FFA,0x3FF6,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x0006,0x3FFA,0x7FFC,0x3FFA,0x0006,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x3FF6,0x7FFA,0xFFFC],
            [0x8002,0xC006,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xC006,0xBFFA,0x7FFC,0x3FFA,0x0006,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x0006,0x0002],
            [0x7FFE,0xBFFC,0xDFF8,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xC000,0xBFF8,0x7FFC,0x3FFA,0x0006,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x3FF6,0x7FFA,0xFFFC],
            [0x7FFE,0xBFFC,0xDFF8,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xE000,0xC000,0xBFF8,0x7FFC,0xBFFA,0xC006,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xDFF6,0xBFFA,0x7FFC],
            [0xFFFC,0x7FFA,0x3FF6,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x0006,0x0002,0x0000,0x0002,0x0006,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x0006,0x0002],
            [0x7FFC,0xBFFA,0xDFF6,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xC006,0xBFFA,0x7FFC,0xBFFA,0xC006,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xDFF6,0xBFFA,0x7FFC],
            [0x7FFC,0xBFFA,0xDFF6,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xE00E,0xC006,0xBFFA,0x7FFC,0x3FFA,0x0006,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x000E,0x3FF6,0x7FFA,0xFFFC],
            [0, 0, 0, 0, 0, 0, 0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0, 0, 0, 0, 0, 0, 0], #:
            [0,0,0, 0, 0, 0, 0, 0, 0, 0,0x1C00,0x1C00,0x1C00,0xFF80,0xFF80,0xFF80,0x1C00,0x1C00,0x1C00,0, 0, 0, 0, 0, 0, 0, 0,0,0],#+
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xFF80,0xFF80,0xFF80,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],#-
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE0,0xE0,0xE0],#.
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0]
        ]
        for i in range(h):
            val = seg7List[num][i]
            for k in range(w):
                tmp = self.fg_color if val & 0x8000 else self.bg_color
                self.pixel(x + k, y + i, tmp)
                val <<= 1

    #刷单字到屏幕像素点: ch_str  单字或连接汉字    x_axis,y_axis  定位点 ch_size  单字大小，默认12，最大16
    def chinese(self,ch_str, x_axis, y_axis, ch_size=12):
        #取模:使用PCtoLCD2002软件
        #1212的点阵: 楷体，阴码，行列式，顺向
        fonts= {
            "网": [0xFF,0x80,0x80,0xC4,0xAA,0x91,0x91,0xAA,0xC4,0x80,0x80,0x80,0xE0,0x20,0x20,0x60,0xA0,0x20,0x20,0xA0,0x60,0x20,0x20,0xE0],#网",0
            "络": [0x22,0x23,0x44,0x9A,0xE1,0x22,0x4C,0xF7,0x04,0x34,0xC7,0x04,0x00,0xC0,0x40,0x80,0x00,0x80,0x60,0xC0,0x40,0x40,0xC0,0x40],#络",1
            "连": [0x82,0x42,0x1F,0x04,0x09,0xCF,0x41,0x41,0x5F,0x41,0x41,0xBF,0x00,0x00,0xE0,0x00,0x00,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0],#连",6
            "接": [0x22,0x21,0x2F,0xF4,0x22,0x2F,0x31,0xEF,0x22,0x26,0x21,0x6E,0x00,0x00,0xE0,0x40,0x80,0xE0,0x00,0xE0,0x40,0x40,0x80,0x60],#接",7
            "中": [0x04,0x04,0x04,0x7F,0x44,0x44,0x44,0x7F,0x44,0x04,0x04,0x04,0x00,0x00,0x00,0xC0,0x40,0x40,0x40,0xC0,0x40,0x00,0x00,0x00],#中",2            
            "成": [0x02,0x02,0x7F,0x42,0x42,0x7A,0x4A,0x4A,0x49,0x5A,0x44,0x88,0x80,0x40,0xE0,0x00,0x00,0x40,0x40,0x80,0x20,0xA0,0x60,0x20],#成",8
            "功": [0x02,0x02,0xFA,0x27,0x22,0x22,0x22,0x22,0x3C,0xC4,0x08,0x10,0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0],#功",9
            "失": [0x04,0x24,0x24,0x3F,0x44,0x84,0x04,0xFF,0x0A,0x11,0x20,0xC0,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0x00,0x00,0x80,0x60],#失",10
            "败": [0x01,0xF9,0x8A,0xAB,0xAC,0xAA,0xAA,0xAA,0xAA,0x21,0x52,0x8C,0x00,0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x80,0x00,0x80,0x60],#败",11
            "未": [0x04,0x04,0x7F,0x04,0x04,0xFF,0x0E,0x15,0x24,0xC4,0x04,0x04,0x00,0x00,0xC0,0x00,0x00,0xE0,0x00,0x00,0x80,0x60,0x00,0x00],#未",0
            "等":[0x42,0x7B,0x94,0x04,0x7F,0x04,0xFF,0x01,0xFF,0x21,0x11,0x07,0x00,0xE0,0x80,0x00,0xC0,0x00,0xE0,0x00,0xE0,0x00,0x00,0x00],#等",0
            "待":[0x11,0x21,0x47,0x91,0x2F,0x60,0xAF,0x20,0x24,0x22,0x20,0x23,0x00,0x00,0xC0,0x00,0xE0,0x80,0xE0,0x80,0x80,0x80,0x80,0x80],#待",1
            
            "调": [0x8F,0x48,0x09,0x0B,0xC9,0x4F,0x48,0x4B,0x4A,0x6B,0x48,0x10,0xE0,0x20,0x20,0xA0,0x20,0xE0,0x20,0xA0,0xA0,0xA0,0x20,0xE0],#调",0
            "频": [0x13,0x5C,0x51,0x53,0xFE,0x12,0x52,0x56,0x8A,0x10,0x21,0xC2,0xE0,0x80,0x00,0xE0,0x20,0xA0,0xA0,0xA0,0xA0,0x80,0x40,0x20],#频",1
            "收": [0x12,0x92,0x92,0x93,0x94,0x9A,0x92,0xB2,0xD1,0x92,0x14,0x18,0x00,0x00,0x00,0xE0,0x40,0x40,0x40,0x80,0x00,0x80,0x40,0x20],#收",2
            "音": [0x04,0x7F,0x20,0x11,0xFF,0x00,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x00,0xC0,0x80,0x00,0xE0,0x00,0xC0,0x40,0xC0,0x40,0xC0,0x40],#音",3
            "机": [0x20,0x27,0x24,0xF4,0x24,0x74,0x6C,0xA4,0x24,0x24,0x28,0x30,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0xA0,0x60],#机",4            
            }
        offset_ = 0
        for k in ch_str:
            byte_data = fonts[k]
            #print(fonts[k], "offset=", offset_)
            for y in range(0, ch_size):
                # 进制转换、补全
                a_ = '{:0>8b}'.format(byte_data[y])
                b_ = '{:0>8b}'.format(byte_data[y+ch_size])
                # 绘制像素点 （按取模软件的行列式方式）
                for x in range(0, 8):
                    color = self.bg_color if int(a_[x]) == 0 else self.fg_color
                    self.pixel(x_axis + offset_ + x, y + y_axis, color)
                    color = self.bg_color if int(b_[x]) == 0 else self.fg_color
                    self.pixel(x_axis + offset_ + x + 8, y + y_axis,color)
            offset_ += ch_size   

tprst = Pin("P7", Pin.OUT_PP, Pin.PULL_NONE)
tpint = Pin("P8", Pin.IN, Pin.PULL_UP)
cst816d = CST816D(i2c,tprst,tpint)

test  = Pin("P9", Pin.OUT_PP)

blk = Pin("P6", Pin.OUT_PP);blk.on()
cs  = Pin("P7", Pin.OUT_OD)
rs = Pin("P3", Pin.OUT_PP)
rst  = Pin("P8", Pin.OUT_PP)
spi = SPI(2, baudrate=40_000_000, polarity=0, phase=0) #P0-mosi, P2-sck
lcd=ST7789(spi, rst=rst, dc=rs, cs=cs, bl=blk, width=240, height=280, rotate_degree=0)  #40M已经达到屏幕的刷新速度极限27ms=37帧/s <- 40000000/(240*280*16)=37.20 和理论值相同
#lcd.fill_rect(0,0,85,30,RED)
i=0
lcd.clear(BLUE)  
lcd.text("TFT TEST", 52, 24,WHITE)#lcd.fg_color)
lcd.text("TP RUN...", 52, 48,WHITE)#lcd.fg_color)
lcd.set_fg_color(RED)
lcd.drawCircle(135, 185, 25, True)
lcd.show()
while True: #https://github.com/russhughes/st7789py_mpy/blob/master/lib/st7789py.py
    '''
    i+=1
    if i==1:
        lcd.clear(RED)
    elif i==2:
        lcd.clear(GREEN)                
    elif i==3:
        i=0
        lcd.clear(BLUE)  
    '''
    
    if cst816d.get_action is True:
        _,pressed,gesture,x,y =  cst816d.get_coord()
        if pressed is True:
            print(gesture,x,y,i)              
    time.sleep_ms(30)


